<?php
/**
 * @copyright ©2018 Lu Wei
 * @author Lu Wei
 * @link http://www.luweiss.com/
 *
 * Created by IntelliJ IDEA.
 * Date Time: 2018/4/13 17:09
 */


namespace luweiss\wechat;


use luweiss\curl\Curl;

/**
 * @property Pay $pay
 * @property Cache $cache
 * @property Curl $curl
 */
class Wechat
{
    public $appId;
    public $appSecret;
    public $mchId;
    public $key;
    public $certPem;
    public $keyPem;

    /** @var  Pay $pay */
    public $pay;

    /** @var Cache $cache */
    public $cache;

    /** @var Curl $curl */
    public $curl;

    public $errCode;
    public $errMsg;
    public $errFun;

    private $accessToken;
    private $hasCheckAccessToken;

    /**
     * Wechat constructor.
     * @param array $args 公众号、小程序等基本参数
     *
     * [
     *
     * 'appId' => '',
     *
     * 'appSecret' => '',
     *
     * 'mchId' => '',
     *
     * 'key' => '',
     *
     * 'certPem' => '',
     *
     * 'keyPem' => '',
     *
     * ]
     */
    public function __construct($args = [])
    {
        $this->appId = isset($args['appId']) ? $args['appId'] : null;
        $this->appSecret = isset($args['appSecret']) ? $args['appSecret'] : null;
        $this->mchId = isset($args['mchId']) ? $args['mchId'] : null;
        $this->key = isset($args['key']) ? $args['key'] : null;
        $this->certPem = isset($args['certPem']) ? $args['certPem'] : null;
        $this->keyPem = isset($args['keyPem']) ? $args['keyPem'] : null;

        $this->pay = new Pay($this);

        $this->curl = new Curl();
        $this->cache = $this->getCache(isset($args['cache']) ? $args['cache'] : []);
    }

    private function getCache($args)
    {
        return new Cache($args);
    }


    /**
     * @param Cache $cache
     * @return $this
     */
    public function setCache($cache)
    {
        $this->cache = $cache;
        return $this;
    }

    /**
     * @param bool $refresh 是否获取新的access token
     * @param int $expire 缓存时间（秒）
     * @return bool|string
     */
    public function getAccessToken($refresh = false, $expire = 7000)
    {
        if ($this->accessToken)
            return $this->accessToken;
        $cacheKey = 'WECHAT_ACCESS_TOKEN_' . $this->appId;
        if ($refresh) {
            $this->accessToken = null;
        } else {
            $this->accessToken = $this->cache->get($cacheKey);
        }
        if ($this->accessToken) {
            if (!$this->hasCheckAccessToken) {
                if ($this->checkAccessToken())
                    return $this->accessToken;
            } else {
                return $this->accessToken;
            }
        }
        $api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
        $res = json_decode($this->curl->get($api), true);
        if (!$res) {
            $this->errCode = $this->curl->curlErrNo;
            $this->errMsg = $this->curl->curlError;
            $this->errFun = __FUNCTION__;
            return false;
        }
        if ($res['errcode'] != 0) {
            $this->errCode = $res['errcode'];
            $this->errMsg = $res['errmsg'];
            $this->errFun = __FUNCTION__;
            return false;
        }
        $this->accessToken = $res['access_token'];
        $this->cache->set($cacheKey, $this->accessToken, $expire);
        return $this->accessToken;
    }

    /**
     * @return bool|string 无效返回false，成功返回accessToken
     */
    public function checkAccessToken()
    {
        if (!$this->accessToken)
            return false;
        $this->hasCheckAccessToken = true;
        $api = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token={$this->accessToken}";
        $res = json_decode($this->curl->get($api), true);
        if (!$res)
            return false;
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            $this->errCode = $res['errcode'];
            $this->errMsg = $res['errmsg'];
            $this->errFun = __FUNCTION__;
            return false;
        }
        return $this->accessToken;
    }

    public function randomString($length = 32)
    {
        // 密码字符集，可任意添加你需要的字符
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            // 这里提供两种字符获取方式
            // 第一种是使用 substr 截取$chars中的任意一位字符；
            // 第二种是取字符数组 $chars 的任意元素
            // $password .= substr($chars, mt_rand(0, strlen($chars) – 1), 1);
            $password .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        return $password;
    }

}